package cz.semjob.learning.data.exporter;

import org.springframework.stereotype.Component;

import cz.semjob.document.annotation.metadata.Relation;
import cz.semjob.learning.data.DataSet;
import cz.semjob.learning.data.IDataSet;
import cz.semjob.learning.data.RelationDataSet;
import cz.semjob.learning.data.attribute.AInstanceAttribute;
import cz.semjob.learning.data.attribute.NominalInstanceAttribute;
import cz.semjob.learning.data.attribute.NumericInstanceAttribute;
import cz.semjob.learning.data.attribute.TextDistributionInstanceAttribute;
import cz.semjob.learning.instances.LabeledRelationInstance;
import cz.semjob.learning.instances.LabeledTextInstance;
import cz.semjob.learning.instances.UnlabeledTextInstance;

@Component
public class ARFFDataSetExporter implements IDataSetExporter {

	public String exportDataSet(IDataSet dataSet) {
		if (dataSet instanceof DataSet) {
			return exportDataSet((DataSet) dataSet);
		} else if (dataSet instanceof RelationDataSet) {
			return exportRelationDataSet((RelationDataSet) dataSet);
		}
		return null;
	}

	private String exportDataSet(DataSet dataSet) {
		StringBuilder dataSetString = createHeader(dataSet);

		String positiveClassLabel = dataSet.getName().toLowerCase();
		String negativeClassLabel = "non-" + dataSet.getName().toLowerCase();

		dataSetString.append("@attribute class { " + positiveClassLabel + ", "
				+ negativeClassLabel + " }\n");

		dataSetString.append("\n");
		dataSetString.append("@data\n");

		for (LabeledTextInstance negativeInstance : dataSet
				.getNegativeInstances()) {
			dataSetString.append(createAttributeString(negativeInstance,
					dataSet, negativeClassLabel));
		}
		for (LabeledTextInstance positiveInstance : dataSet
				.getPositiveInstances()) {
			dataSetString.append(createAttributeString(positiveInstance,
					dataSet, positiveClassLabel));
		}
		return dataSetString.toString();
	}

	private StringBuilder createHeader(IDataSet dataSet) {
		StringBuilder dataSetString = new StringBuilder();
		dataSetString.append("@relation " + dataSet.getName() + "\n");
		dataSetString.append("\n");

		for (AInstanceAttribute attribute : dataSet.getAttributesList()) {
			String attrName = attribute.getName();
			if (attribute instanceof NumericInstanceAttribute) {
				dataSetString.append("@attribute " + attrName + " numeric");
			} else if (attribute instanceof NominalInstanceAttribute) {
				NominalInstanceAttribute nominalAttribute = (NominalInstanceAttribute) attribute;
				String[] values = nominalAttribute.getValues();
				dataSetString.append("@attribute " + attrName + " {");
				for (String value : values) {
					dataSetString.append(value + ", ");
				}
				dataSetString.append("0"); // not defined value
				dataSetString.append("}");
			} else if (attribute instanceof TextDistributionInstanceAttribute) {
				dataSetString.append("@attribute " + attrName + " numeric");
			} else {
				dataSetString.append("@attribute " + attrName + " string");
			}
			dataSetString.append("\n");
		}
		return dataSetString;
	}

	private String createAttributeString(UnlabeledTextInstance instance,
			IDataSet dataSet, String classLabel) {
		StringBuilder attributeString = new StringBuilder();
		for (AInstanceAttribute attribute : dataSet.getAttributesList()) {
			if (instance.getAttributeValues().containsKey(attribute.getName())) {
				attributeString.append(instance.getAttributeValues()
						.get(attribute.getName()).getAttrValue()
						+ ",");
			} else {
				attributeString.append("0,");
			}
		}
		attributeString.append(classLabel);
		attributeString.append("\n");
		return attributeString.toString();
	}

	private String exportRelationDataSet(RelationDataSet dataSet) {
		StringBuilder dataSetString = createHeader(dataSet);
		dataSetString.append("@attribute class { ");
		for (Relation relation : dataSet.getRelations()) {
			dataSetString.append(relation.getName() + ", ");
		}
		dataSetString.deleteCharAt(dataSetString.length() - 1);
		dataSetString.append(" }\n");
		// dataSetString.append(AnnotationTypeFactory.getNoneRelation().getName()
		// + " }\n");

		dataSetString.append("\n");
		dataSetString.append("@data\n");

		// for (LabeledRelationInstance negativeInstance : dataSet
		// .getNegativeInstances()) {
		// dataSetString.append(createAttributeString(negativeInstance,
		// dataSet, "none"));
		// }
		for (LabeledRelationInstance positiveInstance : dataSet
				.getPositiveInstances()) {
			dataSetString.append(createAttributeString(positiveInstance,
					dataSet, positiveInstance.getLabel().getName()));
		}
		return dataSetString.toString();
	}

}
